package cn.ybk.basic.service.impl;

import cn.ybk.basic.constant.RegisterCons;
import cn.ybk.basic.dto.PhoneDto;
import cn.ybk.basic.dto.phoneRegisterFormDto;
import cn.ybk.basic.service.PhoneCodeService;
import cn.ybk.basic.util.BusinessException;
import cn.ybk.basic.util.StrUtils;
import cn.ybk.user.domain.Logininfo;
import cn.ybk.user.domain.User;
import cn.ybk.user.mapper.LogininfoMapper;
import cn.ybk.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.style.DefaultToStringStyler;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class PhoneCodeServiceImpl implements PhoneCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    // 发送手机验证码
    @Override
    public void smsCode(phoneRegisterFormDto dto) {
        if (dto.getType().equals("binder")) {
            this.send(dto, RegisterCons.BINDER_CODE_KEY);
        } else if (dto.getType().equals("register")) {
            // 校验参数等
            this.verify(dto);
            // 发送手机验证码等
            this.send(dto, RegisterCons.REGISTER_CODE_KEY);
        }

    }

    /*
     * 点击注册接口
     */
    @Override
    public void phoneRegister(PhoneDto dto) {
        // 校验参数等
        this.verify(dto);
        // 添加到数据库
        this.add(dto);
    }

    // 注册中添加数据库
    private void add(PhoneDto dto) {
        // 存入数据库
        // 先存入logininfo表中
        User user = dto.getUser();
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user, logininfo);
        logininfo.setType(1);
        logininfo.setDisable(true);
        logininfoMapper.add(logininfo);
        user.setLogininfoId(logininfo.getId());
        userMapper.add(user);
    }

    // 注册中校验参数
    private void verify(PhoneDto dto) {
        // 校验参数
        // 密码是否相同
        if (!dto.getPassword().equals(dto.getPasswordRepeat())) {
            throw new BusinessException("两次密码不一致哟");
        }
        // 手机验证码是否正确
        String phone = (String) redisTemplate.opsForValue().get(String.format(RegisterCons.REGISTER_CODE_KEY, dto.getPhone()));
        if (phone == null || !phone.equals(dto.getPhoneCode())) {
            throw new BusinessException("手机验证码不相同");
        }
        // 手机号是否注册过
        User userPhone = userMapper.findByPhone(dto.getPhone());
        if (userPhone != null) {
            throw new BusinessException("该号码已经被注册了哟！");
        }
    }

    // 发送验证码等
    private void send(phoneRegisterFormDto dto, String redisKey) {
        // 4.判断手机号验证码两次发送时间是否大于60秒
        Long expire = redisTemplate.getExpire(String.format(redisKey, dto.getPhone()));
        if (expire > RegisterCons.CODE_TIME - 1 * 60L) {
            throw new BusinessException("已经发送手机验证码60秒内请别在点击");
        }
        // 5.是否需要重新生成手机号验证码
        // 基于我们目前reids中有手机号验证码 如果有 我们就发送老的 没有我们就生成一个新的
        String getPhoneAgain = (String) redisTemplate.opsForValue().get(String.format(redisKey, dto.getPhone()));

        if (StringUtils.isBlank(getPhoneAgain)) {
            getPhoneAgain = StrUtils.getRandomString(6);
        }
        log.info("验证码是：{}", getPhoneAgain);
        // 6.将手机号验证码存到redis
        redisTemplate.opsForValue().set(String.format(redisKey, dto.getPhone()), getPhoneAgain,
                RegisterCons.CODE_TIME, TimeUnit.SECONDS);

        // 7.发送短信
//        SendSmsUtil.send();
    }

    // 校验参数等
    private void verify(phoneRegisterFormDto dto) {
        // 1.参数验证
        // 2.图形验证码是否正确
        // 从redis中获取到图形验证码 然后和dto中的图形验证码进行比较
        // 获取redis中的key就能获取到value
        String imageCode = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        // StringUtils.isBlank就是判断非空，但是它能够判断三种情况是否为null 是否为“ ”是否是空字符串
        if (StringUtils.isBlank(imageCode) || !imageCode.equalsIgnoreCase(dto.getImageCodeValue())) {
            throw new BusinessException("图片验证码错误哟");
        }
        // 3.手机号是否注册过
        // 根据dto中的手机号查询user表中是否有数据
        User userPhone = userMapper.findByPhone(dto.getPhone());
        if (userPhone != null) {
            throw new BusinessException("该号码已经被注册了哟！");
        }
    }
}

